/*
 * 2006-04-18 Li Ximing, Zhang Yanbo - Create.
 */
package com.hd123.rumba.log;

import java.util.Enumeration;

import org.apache.log4j.Appender;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.AppenderAttachable;

import com.hd123.rumba.request.Action;
import com.hd123.rumba.request.BuffaloSession;

/**
 * Action日志生成器。
 * <p>
 * 
 * 用于记录用户操作跟踪信息写入，这些信息可通过log4j配置写入到数据库中，以便提供给最终企业管理员。
 * 
 * @author lxm
 * @author zhangyanbo
 * 
 */
public class ActionLogger implements AppenderAttachable {

  private Logger logger;
  private Action action;

  /* 公共事件常量 */
  public static final String EVENT_LIST = "列表";
  public static final String EVENT_VIEW = "查看";
  public static final String EVENT_CREATE = "新增";
  public static final String EVENT_EDIT = "编辑";
  public static final String EVENT_SAVENEW = "新增保存";
  public static final String EVENT_SAVE = "保存";
  public static final String EVENT_RECYCLE_LIST = "列表(回收站)";
  public static final String EVENT_DELETE = "删除";
  public static final String EVENT_UNDELETE = "恢复删除";

  protected ActionLogger() {
    // Do Nothing
  }

  public ActionLogger(Action action) {
    if (action == null) {
      Logger.getLogger(ActionLogger.class).warn(
          "ActionLogger()的传入参数action意外的为null。此信息表示可能无法保证日志信息被正确记录。");
      this.logger = Logger.getLogger(Action.class);
    } else
      this.logger = Logger.getLogger(action.getClass());
    this.action = action;
  }

  public static ActionLogger getLogger(Action action) {
    return new ActionLogger(action);
  }

  private String settleNo = null;

  /** 属性：Action */
  public Action getAction() {
    return action;
  }

  /** 属性：Action */
  public void setAction(Action action) {
    this.action = action;
  }

  /**
   * 属性：月度结转期号，允许空<br>
   * 注：对于rumba而言，暂时没有任何含义，保留为未来扩展。
   */
  public String getSettleNo() {
    return settleNo;
  }

  /**
   * 属性：月度结转期号，允许空<br>
   * 注：对于rumba而言，暂时没有任何含义，保留为未来扩展。
   */
  public void setSettleNo(String settleNo) {
    this.settleNo = settleNo;
  }

  /**
   * 写跟踪信息。<br>
   * log.level = Level.INFO。
   * 
   * @param event
   *          日志的事件属性
   * @param message
   *          日志的消息
   */
  public void info(String event, String message) {
    this.logger.info(encodeMessage(event, message));
  }

  /**
   * 写日志。
   * 
   * @param event
   *          日志的事件属性
   * @param message
   *          日志的消息
   * @return IActionLog
   * @deprecated 被{@link #info(String, String)}取代。将在未来版本中被删除。
   */
  public IActionLog logT(String event, String message) {
    this.logger.info(encodeMessage(event, message));
    return null;
  }

  public void addAppender(Appender arg0) {
    this.logger.addAppender(arg0);
  }

  public Enumeration getAllAppenders() {
    return this.logger.getAllAppenders();
  }

  public Appender getAppender(String arg0) {
    return this.logger.getAppender(arg0);
  }

  public boolean isAttached(Appender arg0) {
    return this.logger.isAttached(arg0);
  }

  public void removeAllAppenders() {
    this.logger.removeAllAppenders();
  }

  public void removeAppender(Appender arg0) {
    this.logger.removeAppender(arg0);
  }

  public void removeAppender(String arg0) {
    this.logger.removeAppender(arg0);
  }

  private String encodeMessage(String event, String message) {
    StringBuffer sb = new StringBuffer();
    try {
      sb.append(ActionDBAppender.PREFIX_MESSAGE); // 写入标记，以便ActionDBAppender识别。
      this.appendProp(sb, ActionDBAppender.KEY_ACTION_CAPTION, action.getCaption());
      String domainUuid = null;
      String operator = null;
      if (action.getDd() != null) {
        domainUuid = action.getDd().getCurrentDomain().getUuid();
        operator = action.getDd().getCurrentUser().getNameCode();
      } else {
        domainUuid = BuffaloSession.getCurrentDomain().getUuid();
        operator = BuffaloSession.getCurrentUser().getNameCode();
      }
      this.appendProp(sb, ActionDBAppender.KEY_DOMAIN_UUID, domainUuid);
      this.appendProp(sb, ActionDBAppender.KEY_OPERATOR, operator);
      this.appendProp(sb, ActionDBAppender.KEY_SETTLENO, this.settleNo);
      this.appendProp(sb, ActionDBAppender.KEY_EVENT, event);
      this.appendProp(sb, ActionDBAppender.KEY_MESSAGE, message);
      return sb.toString();
    } catch (Exception e) {
      return message;
    }
  }

  private void appendProp(StringBuffer sb, String caption, String value) {
    if (value == null)
      return;
    if (sb.length() > 0)
      sb.append("#");
    sb.append(caption);
    sb.append("=");
    sb.append(value);
  }
}
